/*
 * Copyright 2008 - 2010 Lars Heuer (heuer[at]semagia.com). All rights reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.semagia.atomico.server.utils;

import java.util.List;

import com.semagia.atomico.MediaType;

/**
 * 
 * 
 * @author Lars Heuer (heuer[at]semagia.com) <a href="http://www.semagia.com/">Semagia</a>
 */
public final class MediaTypeUtils {

    private MediaTypeUtils() {
        // noop.
    }

    /**
     * Returns that media type which is most suitable to satisfy the client's
     * preference.
     * 
     * @param supportedMediaTypes The supported media types (server-side).
     * @param acceptedMediaTypes The preferred media types (client-side).
     * @return A media type which may satisfy the client or {@code null} if no
     *          suitable media type was found.
     */
    public static MediaType getPreferredMediaType(
            List<MediaType> supportedMediaTypes,
            List<MediaType> acceptedMediaTypes) {
        if (acceptedMediaTypes.isEmpty()) {
            return supportedMediaTypes.get(0);
        }
        int bestMatchCount = -1;
        MediaType bestMatch = null;
        for (MediaType mt: acceptedMediaTypes) {
            String type = mt.getType();
            String subType = mt.getSubtype();
            if (bestMatch == null && "*".equals(type) && "*".equals(subType)) {
                bestMatch = supportedMediaTypes.get(0);
                continue;
            }
            for (MediaType supportedMediaType: supportedMediaTypes) {
                int matchCount = 0;
                if (type.equals(supportedMediaType.getType())) {
                    ++matchCount;
                }
                else {
                    --matchCount;
                }
                if (subType.equals(supportedMediaType.getSubtype())) {
                    ++matchCount;
                }
                else {
                    --matchCount;
                }
                if (bestMatchCount < matchCount) {
                    bestMatchCount = matchCount;
                    bestMatch = supportedMediaType;
                }
            }
        }
        return bestMatch;
    }

    /**
     * Returns that media type which is most suitable to satisfy the client's
     * preference.
     * 
     * If no suitable media type was found, the {@code defaultMediaType}
     * is returned (may be {@code null}).
     *
     * @param supportedMediaTypes The supported media types (server-side).
     * @param acceptedMediaTypes The preferred media types (client-side).
     * @return A media type which may satisfy the client or {@code defaultMediaType} 
     *          if no suitable media type was found.
     */
    public static MediaType getPreferredMediaType(final List<MediaType> supportedMediaTypes, final List<MediaType> acceptedMediaTypes, final MediaType defaultMediaType) {
        final MediaType mediaType = getPreferredMediaType(supportedMediaTypes, acceptedMediaTypes);
        return mediaType != null ? mediaType : defaultMediaType;
    }

}
